#include "PlanFileDao.hpp"
#include <boost/lexical_cast.hpp>
#include <boost/throw_exception.hpp>

namespace fixstoker {

PlanFileDao::PlanFileDao() {
}

PlanFileDao::~PlanFileDao() {
}

const Plan*
PlanFileDao::load(const char* fileName) const {
	return 0;
}

void
PlanFileDao::splitLine(const std::string& line, std::vector<std::string>* outVector) const {
	using namespace std;
	using namespace boost;

	typedef boost::tokenizer<boost::char_separator<char> > tokenizer_t;

	boost::char_separator<char> separator(":");
	tokenizer_t tokenizer(line, separator);

	for (tokenizer_t::const_iterator it = tokenizer.begin(); it != tokenizer.end(); ++it) {
		outVector->push_back(*it);
	}
}

void
PlanFileDao::loadTemplate(const std::vector<std::string>& tokens, Plan* plan) {
	using namespace std;
	using namespace boost;

	// template:TEMPLATE_NAME:10=11|123=333

	if (tokens.size() != 3) {
		BOOST_THROW_EXCEPTION(invalid_argument("Cannot load template, expected number of tokens is 3, but got "
				+ lexical_cast<string>(tokens.size())));
	}

	plan->addMessageTemplate(tokens[2]);

	int newIndex = codeToIndexMap_.size();
	this->codeToIndexMap_[tokens[1]] = newIndex;
}

void
PlanFileDao::loadEntry(const std::vector<std::string>& tokens, Plan* plan) {
	using namespace std;
	using namespace boost;

	// memcpy:TEMPLATE_NAME:10,25,value:30,33,value2

	if (tokens.size() < 3) {
		BOOST_THROW_EXCEPTION(invalid_argument("Cannot load entry, expected number of tokens 3 or more, but got "
						+ lexical_cast<string>(tokens.size())));
	}

	// resolve template code to template index
	const string& templateCode = tokens[1];
	const int templateIndex = codeToIndexMap_[templateCode];

	const int substitutionNum = tokens.size() - 2;
	vector<const Substitution*> substitutionVector(substitutionNum);

	for (int indx = 0; indx < substitutionNum; ++indx) {
		const string& substString = tokens[indx + 2];
		substitutionVector[indx] = loadSubstitution(substString);
	}

	PlanEntry* entry = new PlanEntry(templateIndex, substitutionVector);
	plan->addEntry(entry);
}

Substitution*
PlanFileDao::loadSubstitution(std::string str) {
	using namespace std;
	using namespace boost;

	typedef boost::tokenizer<boost::char_separator<char> > tokenizer_t;

	boost::char_separator<char> separator(",");
	tokenizer_t tokenizer(str, separator);

	substitutionTokensTmp_.clear();
	for (tokenizer_t::const_iterator it = tokenizer.begin(); it != tokenizer.end(); ++it) {
		substitutionTokensTmp_.push_back(*it);
	}

	if (substitutionTokensTmp_.size() != 3) {
		BOOST_THROW_EXCEPTION(invalid_argument("Invalid substitution string: "  + str));
	}

	Substitution* result = new Substitution(lexical_cast<int>(substitutionTokensTmp_[0]),
			lexical_cast<int>(substitutionTokensTmp_[1]),
			substitutionTokensTmp_[2].c_str());

	return result;
}

//bool parseMessageTemplates(char const* str,
//		map<const char*, const char*> msgTemplates) {
//	// ( <KEY> ':' <MESSAGE_TEMPLATE> <EOL> )+
//
//}

/*
const Plan*
PlanFileDao::load(std::istream_iterator<char>& input) const {
	using namespace std;
	using namespace boost;



	char_separator<char> sep("", ";", keep_empty_tokens);
	typedef boost::tokenizer<char_separator<char>, istream_iterator<char> > tokenizer_t;
	tokenizer_t tokens(input, inputEnd, sep);

	for (tokenizer_t::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
		cout << "token: '" << *tok_iter << "'" << endl;
	}

	return 0;
}
*/


}
